<script setup lang="ts">
import { ref, computed, h, onMounted } from 'vue'
import {
  NDataTable,
  NButton,
  NIcon,
  NModal,
  NInput,
  NInputNumber,
  NSwitch,
  NSelect,
  NSpace,
  NForm,
  NFormItem,
  NTag
} from 'naive-ui'
import {
  Code,
  Plus,
  Settings,
  Trash,
  AlignLeft,
  ListNumbers,
  List,
  Typography,
  GripVertical
} from '@vicons/tabler'
import { fetchVariables, addVariable, updateVariable, deleteVariable } from '@/service/api/build'
import CustomTooltip from '@/components/CustomTooltip.vue'

type VariableType = 'text' | 'paragraph' | 'dropdown' | 'number'

interface Variable {
  key: string
  name: string
  type: VariableType
  optional: boolean
  maxLength?: number
  options?: string[]
}

const variables = ref<Variable[]>([])

const showModal = ref(false)
const currentVariable = ref<Variable | null>(null)
const selectedType = ref<VariableType>('text')
const draggedItem = ref<number | null>(null)
const draggedOverItem = ref<number | null>(null)
const formRef = ref(null)
const variableTypeMap = {
  text: '文本',
  paragraph: '段落',
  dropdown: '选项',
  number: '数字'
}
const isVariablesEmpty = computed(() => variables.value?.length === 0)

const variableTypes = [
  { type: 'text' as VariableType, icon: Typography, label: '文本' },
  { type: 'paragraph' as VariableType, icon: AlignLeft, label: '段落' },
  { type: 'dropdown' as VariableType, icon: List, label: '选项' },
  { type: 'number' as VariableType, icon: ListNumbers, label: '数字' }
]

const showOptions = computed(() => selectedType.value === 'dropdown')
const showMaxLength = computed(() => ['text', 'paragraph'].includes(selectedType.value))

const rules = {
  name: {
    required: true,
    trigger: ['input', 'blur'],
    message: '变量名不能为空'
  },
  key: {
    required: true,
    trigger: ['input', 'blur'],
    message: '变量key不能为空'
  },
  type: {
    required: true,
    trigger: ['input', 'blur'],
    message: '变量类型不能为空'
  },
  options: {
    required: true,
    trigger: ['input', 'blur'],
    validator: (rule: any, value: string[]) => {
      if (selectedType.value === 'dropdown') {
        if (!value || value.length === 0) {
          return new Error('下拉选项不能为空')
        }
        if (value.some((option) => option.trim() === '')) {
          return new Error('选项不能为空')
        }
      }
      return true
    }
  },
  maxLength: {
    trigger: ['input', 'blur'],
    validator: (rule: any, value: number | undefined) => {
      if (showMaxLength.value && (value === undefined || value <= 0)) {
        return new Error('最大长度必须大于0')
      }
      return true
    }
  }
}

const loadVariables = async () => {
  try {
    const result = await fetchVariables()
    variables.value = Array.isArray(result) ? result : []
  } catch (error) {
    console.error('Failed to load variables:', error)
    variables.value = []
  }
}

const handleAddVariable = () => {
  currentVariable.value = {
    key: '',
    name: '',
    type: selectedType.value,
    optional: false,
    maxLength: undefined,
    options: selectedType.value === 'dropdown' ? [''] : undefined
  }
  showModal.value = true
}

const saveVariable = () => {
  formRef.value?.validate(async (errors: any) => {
    if (!errors && currentVariable.value) {
      currentVariable.value.type = selectedType.value
      if (selectedType.value !== 'dropdown') {
        currentVariable.value.options = undefined
      }
      if (!showMaxLength.value) {
        currentVariable.value.maxLength = undefined
      }
      try {
        if (variables.value.some((v) => v.key === currentVariable.value!.key)) {
          await updateVariable(currentVariable.value)
        } else {
          await addVariable(currentVariable.value)
        }
        await loadVariables()
        showModal.value = false
        currentVariable.value = null
      } catch (error) {
        console.error('Failed to save variable:', error)
      }
    }
  })
}

const editVariable = (variable: Variable) => {
  currentVariable.value = JSON.parse(JSON.stringify(variable))
  selectedType.value = variable.type
  showModal.value = true
}

const removeVariable = async (key: string) => {
  try {
    await deleteVariable(key)
    await loadVariables()
  } catch (error) {
    console.error('Failed to remove variable:', error)
  }
}

const addOption = () => {
  if (currentVariable.value) {
    currentVariable.value.options = currentVariable.value.options || []
    currentVariable.value.options.push('')
  }
}

const removeOption = (index: number) => {
  if (currentVariable.value && currentVariable.value.options) {
    currentVariable.value.options.splice(index, 1)
  }
}

const onDragStart = (e: DragEvent, index: number) => {
  if (e.dataTransfer) {
    e.dataTransfer.effectAllowed = 'move'
    e.dataTransfer.setData('text/plain', index.toString())
  }
  draggedItem.value = index
}

const onDragOver = (e: DragEvent, index: number) => {
  e.preventDefault()
  draggedOverItem.value = index
}

const onDrop = (e: DragEvent, index: number) => {
  e.preventDefault()
  const draggedIndex = parseInt(e.dataTransfer!.getData('text/plain'), 10)
  if (currentVariable.value && currentVariable.value.options) {
    const item = currentVariable.value.options[draggedIndex]
    currentVariable.value.options.splice(draggedIndex, 1)
    currentVariable.value.options.splice(index, 0, item)
  }
  draggedItem.value = null
  draggedOverItem.value = null
}

const columns = [
  {
    title: '变量名称',
    key: 'key',
    render: (row: Variable) => {
      return h(NInput, {
        value: row.key,
        size: 'small',
        onUpdateValue: (value) => (row.key = value)
      })
    }
  },
  {
    title: '显示名称',
    key: 'name',
    render: (row: Variable) => {
      return h(NInput, {
        value: row.name,
        size: 'small',
        onUpdateValue: (value) => (row.name = value)
      })
    }
  },
  {
    title: '类型',
    key: 'type',
    width: 120,
    align: 'center',
    render: (row: Variable) =>
      h(
        NTag,
        {
          size: 'small',
          type: 'info'
        },
        () => variableTypeMap[row.type]
      )
  },
  {
    title: '必填',
    key: 'optional',
    render: (row: Variable) =>
      h(NSwitch, {
        checkedValue: true,
        uncheckedValue: false,
        value: row.optional,
        size: 'small',
        onUpdateValue: (value) => (row.optional = !value)
      })
  },
  {
    title: '操作',
    key: 'actions',
    align: 'center',
    width: 80,
    render: (row: Variable) => {
      return h(
        'div',
        {
          size: 'small',
          class: 'w-full justify-center flex gap-2 items-center'
        },
        [
          h(NButton, { text: true, size: 'small', onClick: () => editVariable(row) }, () =>
            h(NIcon, { component: Settings, size: 18, color: '#868e96' })
          ),
          h(NButton, { text: true, size: 'small', onClick: () => removeVariable(row.key) }, () =>
            h(NIcon, { component: Trash, size: 18, color: '#f03e3e' })
          )
        ]
      )
    }
  }
]

// 在组件挂载时加载变量
onMounted(() => {
  loadVariables()
})
</script>

<template>
  <div class="w-full p-4 rounded-lg bg-#F9F9F9">
    <div class="flex items-center justify-between mb-4">
      <div class="flex items-center justify-center">
        <n-icon size="20" :component="Code" color="#2970FF" />
        <span class="ml-2 text-lg font-medium mr-1">编辑变量</span>
        <CustomTooltip content="变量是用户在对话中提供的信息，可以用于生成更准确的回复。" placement="right" />
      </div>
      <n-button quaternary @click="handleAddVariable" size="small" class="rounded-lg">
        <template #icon>
          <n-icon size="13"><Plus /></n-icon>
        </template>
        添加
      </n-button>
    </div>
    <div class="mb-4 text-#787878 text-sm text-center" v-if="!variables || variables.length === 0">
      变量能使用户输入表单引入提示词或开场白，你可以试试在提示词中输入'\{' 触发变量
    </div>
    <div class="w-full h-full p-4" v-else>
      <n-data-table :columns="columns" :data="variables" style="border-radius: 15px" size="small">
      </n-data-table>
    </div>
  </div>

  <n-modal
    v-model:show="showModal"
    居中显示
    :style="{ width: '460px', top: 'calc(50% - 200px)' }"
    preset="card"
    title="编辑变量"
    :mask-closable="false"
    class="rounded-2xl"
  >
    <n-form
      v-if="currentVariable"
      :model="currentVariable"
      label-placement="top"
      label-width="auto"
      require-mark-placement="right-hanging"
      :rules="rules"
      ref="formRef"
    >
      <n-form-item label="字段类型" path="type" class="w-full">
        <div class="grid grid-cols-4 gap-2 w-full">
          <div
            v-for="type in variableTypes"
            :key="type.type"
            :class="{
              'flex items-center p-2 rounded-xl cursor-pointer transition-colors flex-col justify-center border-1px border-solid': true,
              'border-gray-100': selectedType !== type.type,
              'bg-blue-50 text-blue-600  border-solid border-blue-600 border-1px':
                selectedType === type.type,
              'hover:bg-gray-100': selectedType !== type.type
            }"
            @click="selectedType = type.type"
          >
            <n-icon :component="type.icon" :size="20" />
            <span>{{ type.label }}</span>
          </div>
        </div>
      </n-form-item>
      <n-form-item label="变量名称" path="key">
        <n-input v-model:value="currentVariable.key" placeholder="请输入" />
      </n-form-item>
      <n-form-item label="显示名称" path="name">
        <n-input v-model:value="currentVariable.name" placeholder="请输入" />
      </n-form-item>
      <n-form-item v-if="showMaxLength" label="最大长度" path="maxLength">
        <n-input-number
          v-model:value="currentVariable.maxLength"
          placeholder="请输入"
          class="w-full"
          :min="1"
        />
      </n-form-item>
      <n-form-item v-if="showOptions" label="选项" path="options">
        <div class="w-full">
          <div
            v-for="(option, index) in currentVariable.options"
            :key="index"
            class="flex items-center mt-2 cursor-pointer w-full text-gray-500 text-13px border border-solid border-gray-300 p-2 rounded-lg"
            draggable="true"
            @dragstart="onDragStart($event, index)"
            @dragover="onDragOver($event, index)"
            @drop="onDrop($event, index)"
          >
            <div class="mr-2 cursor-move justify-center items-center h-full">
              <n-icon :component="GripVertical" size="18" />
            </div>
            <n-input
              v-model:value="currentVariable.options[index]"
              class="flex-grow mr-2"
              style="border: 0; outline: 0"
            />
            <n-button circle text type="error" @click="removeOption(index)">
              <template #icon>
                <n-icon :component="Trash" />
              </template>
            </n-button>
          </div>
          <div
            class="flex items-center mt-2 cursor-pointer w-full text-gray-500 text-13px border border-solid border-gray-300 p-2 rounded-lg"
            @click="addOption"
          >
            <n-icon :component="Plus" class="mr-2" size="18" />
            点击添加新选项
          </div>
        </div>
      </n-form-item>
      <n-form-item label="必填" path="optional">
        <n-switch v-model:value="currentVariable.optional" />
      </n-form-item>
    </n-form>
    <template #footer>
      <div class="flex justify-end">
        <n-button @click="showModal = false">取消</n-button>
        <n-button type="primary" class="ml-2" @click="saveVariable">保存</n-button>
      </div>
    </template>
  </n-modal>
</template>

<style scoped>
.cursor-move {
  cursor: move;
}
::v-deep(.n-data-table-wrapper) {
  border-radius: 15px;
}
</style>
